﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Media;
using System.Runtime.InteropServices;
using System.Windows.Interop;


namespace EveruWPF.Windows.Helpers
{
    public class WindowHelper
    {

        #region GlassFrameExtentionProperty
        public static readonly DependencyProperty GlassFrameExtentionProperty = DependencyProperty.RegisterAttached("GlassFrameExtention", typeof(Thickness), typeof(Window), new PropertyMetadata(new PropertyChangedCallback(GlassFrameExtentionChanged)));

        static void GlassFrameExtentionChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            try
            {
                ((Window)sender).Background = Brushes.Transparent;

                if (((Window)sender).IsInitialized == false)
                {
                    ((Window)sender).SourceInitialized += new EventHandler(WindowHelper_SourceInitialized_GlassFrameExtention);
                }
                else
                {
                    ExtendGlassframe((Window)sender, (Thickness)e.NewValue);
                }
            }
            catch { }
        }

        static void WindowHelper_SourceInitialized_GlassFrameExtention(object sender, EventArgs e)
        {
            ExtendGlassframe((Window)sender, (Thickness)((Window)sender).GetValue(GlassFrameExtentionProperty));
        }

        public static void SetGlassFrameExtention(Window element, Thickness value)
        {
            element.SetValue(GlassFrameExtentionProperty, value);
        }

        public static Thickness GetGlassFrameExtention(UIElement element)
        {
            return (Thickness)element.GetValue(GlassFrameExtentionProperty);
        }
        #endregion

        #region AllowWindowDragging
        public static readonly DependencyProperty AllowWindowDraggingProperty = DependencyProperty.RegisterAttached("AllowWindowDragging", typeof(bool), typeof(Window), new PropertyMetadata(true, new PropertyChangedCallback(AllowWindowDraggingChanged)));

        private static void AllowWindowDraggingChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            if (sender.GetType().BaseType == typeof(Window))
            {
                Window wnd = (Window)sender;

                if (wnd.IsInitialized)
                {
                    if (((bool)e.NewValue) == true)
                    {
                        AllowWindowDragging(wnd);
                    }
                    else
                    {
                        PreventWindowDragging(wnd);
                    }
                }
                else
                {
                    wnd.SourceInitialized += (object sender2, EventArgs e2) =>
                        {
                            if (((bool)e.NewValue) == true)
                            {
                                AllowWindowDragging(wnd);
                            }
                            else
                            {
                                PreventWindowDragging(wnd);
                            }
                        };
                }   




            }
        }

        public static void SetAllowWindowDragging(Window element, bool value)
        {
            element.SetValue(AllowWindowDraggingProperty, value);
        }

        public static bool GetAllowWindowDragging(Window element)
        {
            return (bool)element.GetValue(AllowWindowDraggingProperty);
        }

        #endregion

        #region ShowIcon

        public static readonly DependencyProperty HasIconProperty = DependencyProperty.RegisterAttached("HasIcon", typeof(bool), typeof(Window), new PropertyMetadata(true, new PropertyChangedCallback(HasIconChanged)));

        private static void HasIconChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            if (sender.GetType().BaseType == typeof(Window))
            {
                Window wnd = (Window)sender;

                if (((bool)e.NewValue) == false)
                {
                    if (wnd.IsInitialized == false)
                    {
                        wnd.SourceInitialized += (object sender2, EventArgs e2) =>
                            {
                                RemoveIcon((Window)sender);
                            };
                    }
                    else
                    {
                        RemoveIcon((Window)sender);
                    }
                }
                else
                {
                    if (wnd.IsInitialized == false)
                    {
                        wnd.SourceInitialized += (object sender2, EventArgs e2) =>
                        {
                            ShowIcon((Window)sender);
                        };
                    }
                    else
                    {
                        ShowIcon((Window)sender);
                    }
                }
            }
        }

        public static void SetHasIcon(Window element, bool value)
        {
            element.SetValue(HasIconProperty, value);
        }

        public static bool GetHasIcon(Window element)
        {
            return (bool)element.GetValue(HasIconProperty);
        }

        #endregion

        #region MaximizeButton
        public static readonly DependencyProperty MaximizeButtonEnabledProperty = DependencyProperty.RegisterAttached("MaximizeButtonEnabled", typeof(bool), typeof(Window), new PropertyMetadata(true, new PropertyChangedCallback(MaximizeButtonEnabledChanged)));

        private static void MaximizeButtonEnabledChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            if (sender.GetType().BaseType == typeof(Window))
            {
                Window wnd = (Window)sender;

                if (wnd.IsInitialized == false)
                {
                    wnd.SourceInitialized += (object sender2, EventArgs e2) =>
                        {
                            UpdateMaximizeButtons((Window)sender);
                        };
                }
                else
                {
                    UpdateMaximizeButtons((Window)sender);
                }
            }
        }

        public static void SetMaximizeButtonEnabled(Window element, bool value)
        {
            element.SetValue(MaximizeButtonEnabledProperty, value);
        }

        public static bool GetMaximizeButtonEnabled(Window element)
        {
            return (bool)element.GetValue(MaximizeButtonEnabledProperty);
        }


        #endregion

        #region MinimizeButton
        public static readonly DependencyProperty MinimizeButtonEnabledProperty = DependencyProperty.RegisterAttached("MinimizeButtonEnabled", typeof(bool), typeof(Window), new PropertyMetadata(true, new PropertyChangedCallback(MinimizeButtonEnabledChanged)));

        private static void MinimizeButtonEnabledChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            if (sender.GetType().BaseType == typeof(Window))
            {
                Window wnd = (Window)sender;

                if (wnd.IsInitialized == false)
                {
                    wnd.SourceInitialized += (object sender2, EventArgs e2) =>
                    {
                        UpdateMinimizeButtons((Window)sender);
                    };
                }
                else
                {
                    UpdateMinimizeButtons((Window)sender);
                }
            }
        }

        public static void SetMinimizeButtonEnabled(Window element, bool value)
        {
            element.SetValue(MinimizeButtonEnabledProperty, value);
        }

        public static bool GetMinimizeButtonEnabled(Window element)
        {
            return (bool)element.GetValue(MinimizeButtonEnabledProperty);
        }


        #endregion



        internal static void ExtendGlassframe(Window GlassWindow, Thickness thx)
        {
            try
            {
                // Obtain the window handle for WPF application
                IntPtr mainWindowPtr = new WindowInteropHelper(GlassWindow).Handle;
                HwndSource mainWindowSrc = HwndSource.FromHwnd(mainWindowPtr);
                mainWindowSrc.CompositionTarget.BackgroundColor = Color.FromArgb(0, 0, 0, 0);

                // Get System Dpi
                System.Drawing.Graphics desktop = System.Drawing.Graphics.FromHwnd(mainWindowPtr);
                float DesktopDpiX = desktop.DpiX;
                float DesktopDpiY = desktop.DpiY;

                // Set Margins
                NonClientRegionAPI.MARGINS margins = new NonClientRegionAPI.MARGINS();

                // Extend glass frame into client area
                // Note that the default desktop Dpi is 96dpi. The  margins are
                // adjusted for the system Dpi.
                margins.cxLeftWidth = Convert.ToInt32(thx.Left * (DesktopDpiX / 96));
                margins.cxRightWidth = Convert.ToInt32(thx.Right * (DesktopDpiX / 96));
                margins.cyTopHeight = Convert.ToInt32(thx.Top * (DesktopDpiY / 96));
                margins.cyBottomHeight = Convert.ToInt32(thx.Bottom * (DesktopDpiX / 96));

                int hr = NonClientRegionAPI.DwmExtendFrameIntoClientArea(mainWindowSrc.Handle, ref margins);
                //
                if (hr < 0)
                {
                    //DwmExtendFrameIntoClientArea Failed
                }
            }
            // If not Vista, paint background white.
            catch (DllNotFoundException)
            {
                Application.Current.MainWindow.Background = Brushes.White;
            }
        }

        internal static void PreventWindowDragging(Window Wnd)
        {
            try
            {
                WindowInteropHelper helper = new WindowInteropHelper(Wnd);
                HwndSource source = HwndSource.FromHwnd(helper.Handle);
                source.AddHook(WndProc_NoMove);
            }
            catch { }
        }

        internal static void AllowWindowDragging(Window Wnd)
        {
            try
            {
                WindowInteropHelper helper = new WindowInteropHelper(Wnd);
                HwndSource source = HwndSource.FromHwnd(helper.Handle);
                source.RemoveHook(WndProc_NoMove);
            }
            catch { }
        }

        internal static void RemoveIcon(Window window)
        {
            IntPtr hwnd = new WindowInteropHelper(window).Handle;

            int extendedStyle = NonClientRegionAPI.GetWindowLong(hwnd, NonClientRegionAPI.GWL_EXSTYLE);
            NonClientRegionAPI.SetWindowLong(hwnd, NonClientRegionAPI.GWL_EXSTYLE, extendedStyle | NonClientRegionAPI.WS_EX_DLGMODALFRAME);

            // Header aktualisieren
            NonClientRegionAPI.SetWindowPos(hwnd, IntPtr.Zero, 0, 0, 0, 0, NonClientRegionAPI.SWP_NOMOVE |
                  NonClientRegionAPI.SWP_NOSIZE | NonClientRegionAPI.SWP_NOZORDER | NonClientRegionAPI.SWP_FRAMECHANGED);
        }

        internal static void ShowIcon(Window window)
        {
            
        }

        internal static void UpdateMaximizeButtons(Window window)
        {
            const int GWL_STYLE = -16;

            IntPtr hwnd = new System.Windows.Interop.WindowInteropHelper(window).Handle;
            long value = NonClientRegionAPI.GetWindowLong(hwnd, GWL_STYLE);

            if ((bool)window.GetValue(MaximizeButtonEnabledProperty))
            {
                value |= NonClientRegionAPI.WS_MAXIMIZEBOX;
            }
            else
            {
                value &= ~NonClientRegionAPI.WS_MAXIMIZEBOX;
            }

            NonClientRegionAPI.SetWindowLong(hwnd, GWL_STYLE, (int)(value));
        }

        internal static void UpdateMinimizeButtons(Window window)
        {
            const int GWL_STYLE = -16;

            IntPtr hwnd = new System.Windows.Interop.WindowInteropHelper(window).Handle;
            long value = NonClientRegionAPI.GetWindowLong(hwnd, GWL_STYLE);

            if ((bool)window.GetValue(MinimizeButtonEnabledProperty))
            {
                value |= NonClientRegionAPI.WS_MINIMIZEBOX;
            }
            else
            {
                value &= ~NonClientRegionAPI.WS_MINIMIZEBOX;
            }

            NonClientRegionAPI.SetWindowLong(hwnd, GWL_STYLE, (int)(value));
        }




        private static IntPtr WndProc_NoMove(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
        {

            switch (msg)
            {
                case NonClientRegionAPI.WM_SYSCOMMAND:
                    int command = wParam.ToInt32() & 0xfff0;
                    if (command == NonClientRegionAPI.SC_MOVE)
                    {
                        handled = true;
                    }
                    break;
                default:
                    break;
            }
            return IntPtr.Zero;
        }




    }
}
